﻿module BoardTool.KillSpecials

open System
open System.Collections.Generic

open BoardTool.DirTree
open BoardTool.Tool
open BoardTool.Board
open BoardTool.Commands

let private SPECIAL_TERRAINS =
    HashSet( ["ice"; "sand"; "snow"] )

let private isSpecialTerrain (t : Terrain) =
    SPECIAL_TERRAINS.Contains( t.Type )

let private hasSpecialTerrain (hex : Hex) =
    hex.Terrains |> List.exists isSpecialTerrain
    
let private getCleanFile (file : string) =
    getPostfixedFile "-clean" file

let private killSpecialsInFile (file : string) =
    match makeBoard <| parseBoardFile file with
    | None ->
        None
    | Some board ->
        if Array.exists hasSpecialTerrain board.Hexes then
            board.Hexes |> Array.iteri 
                (fun i hex ->
                    let terrains' = List.filter (isSpecialTerrain >> not) hex.Terrains
                    board.Hexes.[i] <- { hex with Terrains = terrains' }
                )
            let file' = getCleanFile file
            unparseBoard file' board
            Some (file, file')
        else
            None

type private KillSpecialsCommand( dir ) =
    inherit MapDirCommand< (string * string) option >( dir )
    override this.Id = sprintf "(killSpecials %s)" dir
    override this.processFile file =
        killSpecialsInFile file
    override this.reduce results =
        let cleanedFiles =
            results.Values
            |> Seq.choose id
            |> Seq.toArray
        printfn ""
        if cleanedFiles.Length > 0 then
            printfn "%d files cleaned:" cleanedFiles.Length
            for srcFile, cleanFile in cleanedFiles do
                printfn "  '%s': from '%s'" cleanFile srcFile
        else
            printfn "No files cleaned."

let KILL_SPECIALS_COMMAND_FACTORY =
    { new MapDirCommandFactory( "killSpecials", "generated a \"clean\" version for each map with special terrain" ) with
        override this.createCommand( dir ) =
            KillSpecialsCommand( dir ) :> ICommand
    }